package com.ctw.mapmycity;

import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.protocol.HTTP;

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.IntentSender;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnDragListener;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.ctw.mapmycity.client.RequestMethod;
import com.ctw.mapmycity.client.RestClient;
import com.ctw.mapmycity.fb.PublishHelper;
import com.ctw.mapmycity.model.CustomMarker;
import com.ctw.mapmycity.model.PostModel;
import com.ctw.mapmycity.model.to.PostConfirmation;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;

public class MapActivity extends Fragment implements 
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {

	/*
	 * Define a request code to send to Google Play services
	 * This code is returned in Activity.onActivityResult
	 */
	private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
	private LocationClient mLocationClient;

	private MapView m;
	private GoogleMap mMap;
	private CameraPosition cameraPostion;
	CustomInfoWindowAdpater customInfoWindow = null;
	LatLng pointFoundOnMap = null;
	Marker currentMarkerFound = null;

	Boolean isAdding = false; // For Loading Address
	boolean isAdd = false; // For SlidingUpPanel
	boolean UpDownToggle = false; // False = Up
	boolean isView = false;
	boolean markerMoved = false;
	private List<Address> addressList;
	View layoutRegisterForm = null;
	SlidingUpPanelLayout sliding_layout = null;
	EditText addressText = null;
	EditText descriptionCrime = null;
	CheckBox shareFacebook = null;
	View viewReady = null;
	Spinner spinnerCrime = null;
	EditText timeCrime = null;
	TextView dateCrime = null;
	Marker lastMarkerSearch = null;
	PostModel currentPost = null;
	ArrayAdapter<CharSequence> adapter = null;
	ImageView arrowUpDown = null;
	CheckBox checkBO = null;
	TextView textCitySate = null;

	private String currentViewPostId;

	public void configSlidingUpDownPanel (){
		Button addpoint = (Button) MapActivity.this.getView().findViewById(R.id.addpoint);
		View viewPosts = (View) MapActivity.this.getView().findViewById(R.id.viewPostShare);

		dateCrime.setEnabled(isAdd);
		timeCrime.setEnabled(isAdd);
		checkBO.setEnabled(isAdd);
		descriptionCrime.setEnabled(isAdd);
		spinnerCrime.setEnabled(isAdd);

		if (isAdd){
			viewPosts.setVisibility(View.GONE);
			addpoint.setVisibility(View.VISIBLE);
			shareFacebook.setVisibility(View.VISIBLE);
			descriptionCrime.setText("");
			textCitySate.setText("");
			checkBO.setChecked(false);
			timeCrime.setText(R.string.set_time_crime);
			dateCrime.setText(R.string.set_date_crime);
			spinnerCrime.setSelection(0);
			shareFacebook.setChecked(false);
		} else {
			viewPosts.setVisibility(View.VISIBLE);
			addpoint.setVisibility(View.GONE);
			shareFacebook.setVisibility(View.GONE);
		}
	}


	public void checkMap(){
		if (mMap == null) {
			mMap = ((MapView) viewReady.findViewById(R.id.mapsCity)).getMap();
			if (mMap != null) {
				setUpMap();
			}
		}
	}

	public void buildListenerEssentialMap(){
		checkMap();	

		mMap.setOnMarkerDragListener(new OnMarkerDragListener() {

			@Override
			public void onMarkerDragStart(Marker marker) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onMarkerDragEnd(Marker marker) {
				markerMoved = true;

				//				sliding_layout.isExpanded();
				if (layoutRegisterForm.isShown()){
					isAdding = true;
					loadAddressByPoint(marker.getPosition());
				}

			}

			@Override
			public void onMarkerDrag(Marker marker) {
				// TODO Auto-generated method stub

			}
		});

		mMap.setOnMapLongClickListener(new OnMapLongClickListener() {

			@Override
			public void onMapLongClick(LatLng point) {
				isAdding = true;
				loadAddressByPoint(point);

			}
		});

		mMap.setOnMarkerClickListener(new OnMarkerClickListener() {

			@Override
			public boolean onMarkerClick(Marker marker) {
				//				marker.setVisible(false);

				marker.hideInfoWindow();
				String snippet = marker.getSnippet();

				if (!snippet.equals("") && snippet != null){

					TextView textAddress = (TextView) MapActivity.this.getView().findViewById(R.id.text_address);
					TextView textCityState = (TextView) MapActivity.this.getView().findViewById(R.id.text_cityState);
					ImageView infoImage = (ImageView) MapActivity.this.getView().findViewById(R.id.arrowpoint);

					isView = true;
					isAdd = false;
					String [] snippetMarker = null;

					if (snippet != null){
						snippetMarker = snippet.split(";");	
					}

					if (!snippet.equals("Found by Address") && !snippet.equals("Found by Click on Map")){

						currentViewPostId = snippetMarker[9];

						// Load all content:
						textAddress.setText(snippetMarker[2] + " - " + snippetMarker[4] + " - " + snippetMarker[5]);
						currentPost = new PostModel();
						currentPost.setType(snippetMarker[2]);
						currentPost.setDate(snippetMarker[4]);
						currentPost.setTime(snippetMarker[5]);
						currentPost.setCity(snippetMarker[0]);
						currentPost.setDescription(snippetMarker[6]);
						currentPost.setBoRegistered(Boolean.parseBoolean(snippetMarker[8]));

						textCityState.setSingleLine(false);
						textCityState.setText(snippetMarker[0]);
						dateCrime.setText(snippetMarker[4]);
						timeCrime.setText(snippetMarker[5]);
						descriptionCrime.setText(snippetMarker[6]);
						spinnerCrime.setSelection(Integer.parseInt(snippetMarker[7]));
						checkBO.setChecked(Boolean.parseBoolean(snippetMarker[8]));

						if  (snippetMarker[2].equals("Furto")){
							infoImage.setImageResource((R.drawable.azure_furto48));
						} else if (snippetMarker[2].equals("Roubo de veiculo")){
							infoImage.setImageResource((R.drawable.chartreuse_rouboveiculo48));
						} else if (snippetMarker[2].equals("Sequestro")){
							infoImage.setImageResource((R.drawable.pink_sequestro48));
						}else if (snippetMarker[2].equals("Homicidio")){
							infoImage.setImageResource((R.drawable.pink_homicio48));
						}else if (snippetMarker[2].equals("Assalto a mao armada")){
							infoImage.setImageResource((R.drawable.azure_maoarmada48));
						} 

						loadAgreements(currentViewPostId);

					} else if (snippet.equals("Found by Address") && markerMoved == false) {
						isView = false;
						isAdd = true;
						lastMarkerSearch = marker;
						textAddress.setText(addressList.get(0).getAddressLine(0));
						textCityState.setText(addressList.get(0).getAddressLine(1));
						infoImage.setImageResource((R.drawable.arrow_up_48));
					} else if (snippet.equals("Found by Address") && markerMoved == true){
						isView = false;
						isAdd = true;
						lastMarkerSearch = marker;
						isAdding = true;
						loadAddressByPoint(marker.getPosition());
						infoImage.setImageResource((R.drawable.arrow_up_48));
					}

					configSlidingUpDownPanel();

					layoutRegisterForm.setVisibility(0);
				}
				return true;
			}
		});
	}

	private void loadAgreements(final String postId){
		new AsyncTask<String, Void, List<String>>() {

			@Override
			protected List<String> doInBackground(String... ids) {
				String id = ids[0];

				Gson gson = new Gson();
				List<String> agreements = null;
				try {
					RestClient client = null;
					client = new RestClient("post/action/confirm/" + id);
					client.AddHeader(HTTP.CONTENT_TYPE, "application/json");

					client.Execute(RequestMethod.GET);
					String response = client.getResponse();

					Type listType = new TypeToken<List<String>>() {}.getType();
					agreements = gson.fromJson(response, listType);

				} catch (Exception e) {}
				
				if (agreements == null)
					agreements = new ArrayList<String>();
				
				return agreements;
			}

			@Override
			protected void onPostExecute(final List<String> agreements) {
				Button agreementsCountView = (Button) MapActivity.this.getView().findViewById(R.id.agrementImage);
				agreementsCountView.setText("Agreements: " + agreements.size());
			}

		}.execute(postId);
	}

	private void doAgree(final String postId, final String userId){
		new AsyncTask<String, Void, List<String>>() {

			@Override
			protected List<String> doInBackground(String... ids) {
				String id = ids[0];
				String uId = ids[1];

				Gson gson = new Gson();
				List<String> agreements = null;
				try {
					RestClient client = null;
					client = new RestClient("post/action/confirm/");
					client.AddHeader("Accept", "application/json");
					client.AddHeader(HTTP.CONTENT_TYPE, "application/json");
					client.AddParam("postConfirmation", gson.toJsonTree(new PostConfirmation(id, uId)).toString());

					client.Execute(RequestMethod.POST);
					String response = client.getResponse();

					Type listType = new TypeToken<List<String>>() {}.getType();
					agreements = gson.fromJson(response, listType);

				} catch (Exception e) {}
				
				if (agreements == null)
					agreements = new ArrayList<String>();
				
				return agreements;
			}

			@Override
			protected void onPostExecute(final List<String> agreements) {
				Button agreementsCountView = (Button) MapActivity.this.getView().findViewById(R.id.agrementImage);
				agreementsCountView.setText("Agreements: " + agreements.size());
			}

		}.execute(postId, userId);
	}


	public void loadAddressByPoint(LatLng point){
		checkMap();
		
		if (isAdding){
			isView = false;
			isAdd = true;
			
			configSlidingUpDownPanel();
			
			layoutRegisterForm.setVisibility(View.VISIBLE);
			ImageView infoImage = (ImageView) MapActivity.this.getView().findViewById(R.id.arrowpoint);
			infoImage.setImageResource((R.drawable.arrow_up_48));
			pointFoundOnMap = point;
			
			final TextView textAddress = (TextView) MapActivity.this.getView().findViewById(R.id.text_address);
			final TextView textCityState = (TextView) MapActivity.this.getView().findViewById(R.id.text_cityState);
			
			MarkerOptions markerOptions = new MarkerOptions().position(point).snippet("Found by Click on Map").icon(BitmapDescriptorFactory.fromResource(R.drawable.search_marker48));	
			markerOptions.draggable(true);
			
			if (lastMarkerSearch != null){
				lastMarkerSearch.setVisible(false);
			}
			
			lastMarkerSearch = currentMarkerFound = mMap.addMarker(markerOptions);
			textAddress.setText("Loading Address...");

			new AsyncTask<LatLng, Void, Address>() {
				@Override
				protected Address doInBackground(LatLng... params) {
					LatLng point = params[0];
					
					Geocoder geocoder = new Geocoder(MapActivity.this.getActivity());
					try {
						//result = (geocoder.getFromLocation(point.latitude, point.longitude, 1)).get(0).getAddressLine(0);
						addressList = geocoder.getFromLocation(point.latitude, point.longitude, 1);
					
					} catch (Exception e) {
						return null;
					}
					
					return addressList.get(0);
				}

				protected void onPostExecute(Address result) {
					if (result != null){
						textAddress.setText(result.getAddressLine(0));
						textCityState.setText(result.getAddressLine(1));
						//    					mMap.setOnMapClickListener(null);
					} else {
						layoutRegisterForm.setVisibility(View.GONE);
						currentMarkerFound.setVisible(false);
						Toast.makeText(MapActivity.this.getActivity(), "Localização não disponível. Por favor tente novamente mais tarde.",  Toast.LENGTH_SHORT).show();
					}

				};
			}.execute(point);
			
			isAdding = false;
		} else if (!sliding_layout.isExpanded() && !isAdding) {
			layoutRegisterForm.setVisibility(View.GONE);
		}
	}


	public void buildListenerClickOnMap(){
		checkMap();
		mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
			@Override
			public void onMapClick(final LatLng point) {
				loadAddressByPoint(point);
				if (currentMarkerFound != null){
					currentMarkerFound.setVisible(false);
					layoutRegisterForm.setVisibility(View.GONE);
				} else if (lastMarkerSearch != null){
					lastMarkerSearch.setVisible(false);
					layoutRegisterForm.setVisibility(View.GONE);
				}
			}
		});
	}

	public void changeSlidingStatusLayout (){
		ImageView infoImage = (ImageView) MapActivity.this.getView().findViewById(R.id.arrowpoint);
		if (sliding_layout.isExpanded()){
			sliding_layout.collapsePane();
			addressText.setEnabled(true);

			getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);           
			InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(
					Context.INPUT_METHOD_SERVICE);
			imm.hideSoftInputFromWindow(descriptionCrime.getWindowToken(), 0);
			descriptionCrime.clearFocus();
			if (!isView & isAdd){
				infoImage.setImageResource((R.drawable.arrow_up_48));	
			} else {
				//				infoImage.setImageResource((R.drawable.info48));
			}
			UpDownToggle = false;
		} else {
			if (!isView & isAdd){
				infoImage.setImageResource((R.drawable.arrow_down_48));	
			} else {
				//				infoImage.setImageResource((R.drawable.info48));
			}
			sliding_layout.expandPane();
			addressText.setEnabled(false);
			UpDownToggle = true;
		}
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		// inflat and return the layout
		View v = inflater.inflate(R.layout.drawer_map_layout, container, false);


		/*
		 * Create a new location client, using the enclosing class to
		 * handle callbacks.
		 */
		mLocationClient = new LocationClient(this.getActivity(), this, this);

		m = (MapView) v.findViewById(R.id.mapsCity);
		m.onCreate(savedInstanceState);
		viewReady = v;

		buildListenerEssentialMap();

		ImageButton plusPoint = (ImageButton) v.findViewById(R.id.plusPoint);
		layoutRegisterForm = (View) v.findViewById(R.id.layout_register_form);

		plusPoint.setOnClickListener(new View.OnClickListener() {
			public void onClick(View arg0) {
				goToCurrentPosition();
			}
		});


		Button shareWithFacebook = (Button) v.findViewById(R.id.justpostfacebook);
		shareWithFacebook.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				PublishHelper.sharePost(MapActivity.this.getActivity(), currentPost);
			}
		});
		textCitySate = (TextView) v.findViewById(R.id.text_cityState);
		addressText = (EditText) v.findViewById(R.id.address_textEdit);
		checkBO = (CheckBox) v.findViewById(R.id.checkbox_boletim);
		addressText.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
		addressText.setImeActionLabel("Procurar", 3);
		addressText.setOnKeyListener(new OnKeyListener() {
			@Override
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				if(keyCode == event.KEYCODE_ENTER){
					if (addressText.getText().toString() != ""){
						AddressService addressService = new AddressService(getActivity(),addressText.getText().toString());
						addressService.execute();
					}
				}
				// TODO Auto-generated method stub
				return false;
			}
		});
		Drawable img = getResources().getDrawable(R.drawable.searchedittext);
		addressText.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null);
		//		addressText.setShadowLayer(2, 2, 2, 0xFF555555); 

		ImageButton searchAddress = (ImageButton) v.findViewById(R.id.action_search);
		searchAddress.setOnClickListener(new View.OnClickListener() {
			public void onClick(View arg0) {
				if (addressText.getText().toString() != ""){
					AddressService addressService = new AddressService(getActivity(),addressText.getText().toString());
					addressService.execute();
				}
			}
		});

		// Spinner - COMBOBOX - Tipo de Crime
		spinnerCrime = (Spinner) v.findViewById(R.id.type_crime);
		// Create an ArrayAdapter using the string array and a default spinner layout
		adapter = ArrayAdapter.createFromResource(getActivity(),
				R.array.type_crimes, android.R.layout.simple_spinner_item);
		// Specify the layout to use when the list of choices appears
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		// Apply the adapter to the spinner
		spinnerCrime.setAdapter(adapter); 

		timeCrime = (EditText) v.findViewById(R.id.set_time_crime);
		timeCrime.setOnClickListener(new View.OnClickListener() {

			public void onClick(View arg0) {
				TimePickerFragment timerPicker = new TimePickerFragment(timeCrime);
				timerPicker.show(getActivity().getFragmentManager(), "setTimePicker");
			}
		});

		dateCrime = (TextView) v.findViewById(R.id.set_date_crime);
		dateCrime.setOnClickListener(new View.OnClickListener() {
			public void onClick(View arg0) {
				DatePickerFragment datePicker = new DatePickerFragment(dateCrime);
				datePicker.show(getActivity().getFragmentManager(), "setDatePicker");
			}
		});
		descriptionCrime = (EditText) v.findViewById(R.id.set_description_crime);
		descriptionCrime.setImeOptions(EditorInfo.IME_ACTION_GO);
		descriptionCrime.setImeActionLabel("Publicar", EditorInfo.IME_ACTION_GO);
		descriptionCrime.setOnKeyListener(new OnKeyListener() {
			@Override
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				if(keyCode == KeyEvent.KEYCODE_ENTER){
					InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(
							Context.INPUT_METHOD_SERVICE);
					imm.hideSoftInputFromWindow(descriptionCrime.getWindowToken(), 0);
					descriptionCrime.clearFocus();
					spinnerCrime.requestFocus();
					return true;
				}
				// TODO Auto-generated method stub
				return false;
			}
		});


		sliding_layout = (SlidingUpPanelLayout) v.findViewById(R.id.sliding_layout);
		sliding_layout.setShadowDrawable(getResources().getDrawable(R.drawable.above_shadow));
		sliding_layout.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				MapActivity.this.changeSlidingStatusLayout();
				return false;
			}
		});

		arrowUpDown = (ImageView) v.findViewById(R.id.arrowpoint);
		arrowUpDown.setOnClickListener(new View.OnClickListener() {
			public void onClick(View arg0) {
				MapActivity.this.changeSlidingStatusLayout();
			}
		});

		arrowUpDown.setOnDragListener(new OnDragListener() {

			@Override
			public boolean onDrag(View v, DragEvent event) {
				MapActivity.this.changeSlidingStatusLayout();
				return false;
			}
		});

		Button addPoint = (Button) v.findViewById(R.id.addpoint);
		addPoint.setOnClickListener(new View.OnClickListener() {
			public void onClick(View arg0) {
				addPointButton();
			}
		});

		shareFacebook = (CheckBox) v.findViewById(R.id.checkbox_facebookshare);

		Button agreeBtn = (Button) v.findViewById(R.id.agrementImage);
		agreeBtn.setOnClickListener(new View.OnClickListener() {
			public void onClick(View arg0) {
				doAgree(currentViewPostId, 
						((MapMyCity) MapActivity.this.getActivity().getApplication()).getLoggedAccount().name
						);
			}
		});
		
		buildListenerClickOnMap();

		return v;
	}

	public void countUpdateListViewCrime(int pos) {
		ListView mDrawerList = (ListView) getActivity().findViewById(R.id.left_drawer);

		//		updateMenuItemCounter(1, newValue)

		//		int total = ((MapMyCity) getActivity().getApplication()).listCustomOptionMarkers.size();
		//		txtView = ((TextView) mDrawerList.getChildAt(1).findViewById(R.id.menurow_counter));
		//		txtView.setText(Integer.toString(total + 1));
		//		
		//		if (!crime.equals("")){
		//
		//			if (crime.equals("Furto"))
		//				txtView = ((TextView) mDrawerList.getChildAt(2).findViewById(R.id.menurow_counter));
		//			if (crime.equals("Roubo de veiculo"))
		//				txtView = ((TextView) mDrawerList.getChildAt(3).findViewById(R.id.menurow_counter));
		//			if (crime.equals("Assalto a mao armada"))
		//				txtView = ((TextView) mDrawerList.getChildAt(4).findViewById(R.id.menurow_counter));
		//			if (crime.equals("Sequestro"))
		//				txtView = ((TextView) mDrawerList.getChildAt(5).findViewById(R.id.menurow_counter));
		//			if (crime.equals("Homicidio"))
		//				txtView = ((TextView) mDrawerList.getChildAt(6).findViewById(R.id.menurow_counter));
		//
		//			txtView.setText(Integer.valueOf(txtView.getText() + "") + 1 + "");
		//		}

	}

	public void updateMenuItemCounter(int pos, int newValue){
		ListView mDrawerList = (ListView) getActivity().findViewById(R.id.left_drawer);
		View view = mDrawerList.getChildAt(pos + 1);
		if (view != null){
			TextView txtView = ((TextView) view.findViewById(R.id.menurow_counter));
			if (txtView != null)
				txtView.setText(newValue + "");
		}
	}


	public void addPointButton(){
		// hide keyboard
		getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);           
		InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.hideSoftInputFromWindow(descriptionCrime.getWindowToken(), 0);


		if (pointFoundOnMap != null){

			int crimeSelected = spinnerCrime.getSelectedItemPosition();

			PostModel postModel =  new PostModel();
			postModel.setTypeKey(crimeSelected);
			postModel.setType(adapter.getItem(crimeSelected).toString());
			postModel.setDescription(descriptionCrime.getText().toString());
			postModel.setTime(timeCrime.getText().toString());
			postModel.setDate(dateCrime.getText().toString());
			postModel.setLatitude(pointFoundOnMap.latitude);
			postModel.setLongitude(pointFoundOnMap.longitude);
			postModel.setCity(addressList.get(0).getAddressLine(1));
			postModel.setAddress(addressList.get(0).getAddressLine(0));
			postModel.setBoRegistered(checkBO.isChecked());

			// TODO check later
			countUpdateListViewCrime(postModel.getTypeKey());

			new AsyncTask<PostModel, Void, PostModel>() {
				@Override
				protected void onPreExecute() {
					//					maskUtil.mask(mContentView, R.string.login_progress_signing_in);
				}

				@Override
				protected PostModel doInBackground(PostModel... postModels) {
					PostModel p = postModels[0];

					Gson gson = new Gson();
					JsonObject jo = new JsonObject();

					try {
						RestClient client = null;
						client = new RestClient("post");
						client.AddHeader("Accept", "application/json");
						client.AddHeader(HTTP.CONTENT_TYPE, "application/json");

						client.AddParam("postModel", gson.toJsonTree(p).toString());

						client.Execute(RequestMethod.POST);

						String response = client.getResponse();

						p = gson.fromJson(response, PostModel.class);

						// TODO REMOVE: just for test
						//						if (shareFacebook.isChecked()) {

						//							client = new RestClient("/post/action/confirm");
						//							client.AddHeader("Accept", "application/json");
						//							client.AddHeader(HTTP.CONTENT_TYPE, "application/json");
						//
						//							client.AddParam("postConfirmation", gson.toJsonTree(new PostConfirmation(p.getId(), p.getUserEmail())).toString());
						//							client.Execute(RequestMethod.POST);

						//						}


					} catch (Exception e) {
						e.printStackTrace();

						p = null;
					}


					return p;
				}

				@Override
				protected void onPostExecute(final PostModel result) {
					isAdd = false;
					
					if (lastMarkerSearch != null){
						lastMarkerSearch.setVisible(false);	
					}

//					configSlidingUpDownPanel();
//					sliding_layout.collapsePane();
//					arrowUpDown.setImageResource((R.drawable.added48));
					changeSlidingStatusLayout();	
					layoutRegisterForm.setVisibility(View.GONE);
					
					buildListenerClickOnMap();
					
					Toast.makeText(getActivity(), "Post relaziado com sucesso.", Toast.LENGTH_SHORT).show();
					
					if (result == null) return;

					if (shareFacebook.isChecked())
						PublishHelper.sharePost(MapActivity.this.getActivity(), result);

					loadPosts();
				}

				@Override
				protected void onCancelled() {
				}

			}.execute(postModel);


		}

		pointFoundOnMap = null;
		isAdding = false;
	}

	public class AddressService extends AsyncTask<Void, Void, String> {

		private Activity context;
		private LatLng point;
		private String address; 
		private List<Address> addressListLocal;
		private String errorMessage;

		public AddressService(Activity context, String address){

			this.context = context;
			this.address = address;
		}

		@Override
		protected void onPreExecute() {

		}

		@Override
		protected String doInBackground(Void... params) {
			Geocoder geocoder = new Geocoder(this.context);
			try {
				addressListLocal = (geocoder.getFromLocationName(address, 5));
				addressList = addressListLocal;
			} catch (Exception e) {
				errorMessage = "Check your connection!";
			}
			return null;
		}

		@Override
		protected void onPostExecute(final String authToken) {

			if (currentMarkerFound != null){
				currentMarkerFound.setVisible(false);
			}

			if (addressListLocal != null && addressListLocal.size() > 0) {
				point = new LatLng(addressListLocal.get(0).getLatitude(),addressListLocal.get(0).getLongitude());
				pointFoundOnMap = point;
				checkMap();
				mMap.moveCamera(CameraUpdateFactory.newLatLng(point));
				mMap.moveCamera(CameraUpdateFactory.zoomTo(15));

				MarkerOptions markerOptions = new MarkerOptions().position(point).snippet("Found by Address").icon(BitmapDescriptorFactory.fromResource(R.drawable.search_marker48));	
				markerOptions.draggable(true);
				currentMarkerFound = mMap.addMarker(markerOptions);
				getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);           
				InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(
						Context.INPUT_METHOD_SERVICE);
				imm.hideSoftInputFromWindow(addressText.getWindowToken(), 0);
				addressText.setText("");
			} else {
				Toast.makeText(getActivity(),
						errorMessage, Toast.LENGTH_LONG)
						.show();
			}
		}

		@Override
		protected void onCancelled() {
			super.onCancelled();
		}
	}

	public void goToCurrentPosition(){

		if (mLocationClient.isConnected()){
			Location location = mLocationClient.getLastLocation();
			
			if (location != null) { 
				LatLng latLng = new LatLng(location.getLatitude(),location.getLongitude());

				checkMap();
				mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
				mMap.moveCamera(CameraUpdateFactory.zoomTo(15));
			} else {
				Toast.makeText(this.getActivity(), "Localização atual não disponível. Por favor tente novamente mais tarde.",  Toast.LENGTH_SHORT).show();
			}
		}
		
		
		// Get Location from User.
		/*		LocationResult locationResult = new LocationResult(){
			@Override
			public void gotLocation(Location location){
				if (location == null) return;

				LatLng latLng = new LatLng(location.getLatitude(),location.getLongitude());
				checkMap();

				mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
				mMap.moveCamera(CameraUpdateFactory.zoomTo(15));
			}
		};*/

		//		GetLocationUser myLocation = new GetLocationUser();
		//		myLocation.getLocation(getActivity(), locationResult);

		//		new AsyncTask<Void, Void, LatLng>() {
		//			@Override
		//			protected void onPreExecute() {
		//			}
		//
		//			@Override
		//			protected LatLng doInBackground(Void... voids) {
		//				return new LatLng(location.getLatitude(),location.getLongitude());;
		//			}
		//
		//			@Override
		//			protected void onPostExecute(LatLng latLng) {
		//				checkMap();
		//				mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
		//				mMap.moveCamera(CameraUpdateFactory.zoomTo(15));
		//			}
		//
		//			@Override
		//			protected void onCancelled() {
		//			}
		//
		//		}.execute();
	}


	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
	}


	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		if (savedInstanceState != null) {
		}
	}


	@Override
	public void onResume() {
		super.onResume();
		m.onResume();
		
		checkMap();
		if (cameraPostion != null){
			mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPostion));
			cameraPostion = null;
		} else {
			goToCurrentPosition();
		}

		loadPosts();
	}
	
	private void loadPosts() {
		checkMap();

		mMap.clear();

		// TODO check user filters

		// just for test, it should not be called onResume
		new AsyncTask<Void, Void, List<PostModel>>() {
			@Override
			protected void onPreExecute() {
			}

			@Override
			protected List<PostModel> doInBackground(Void... voids) {
				List<PostModel> posts = new ArrayList<PostModel>();

				// TODO remove
				if (mMap == null ) {
					return posts;
				}

				Gson gson = new Gson();
				try {
					RestClient client = null;
					client = new RestClient("/post/posts");
					client.AddHeader("Accept", "application/json");
					client.Execute(RequestMethod.GET);

					String response = client.getResponse();

					Type listType = new TypeToken<List<PostModel>>() {}.getType();
					posts = gson.fromJson(response, listType);

				} catch (Exception e) {}
				
				if (posts == null)
					posts = new ArrayList<PostModel>();

				return posts;
			}

			@Override
			protected void onPostExecute(final List<PostModel> posts) {

				// TODO remove
				if (mMap == null ) return;

				ListView mDrawerList = (ListView) getActivity().findViewById(R.id.left_drawer);
				View view = mDrawerList.getChildAt(8);
				if (view != null){
					TextView txtView = ((TextView) view.findViewById(R.id.menurow_title));
					if (txtView != null)
						txtView.setText(getResources().getString(R.string.ns_menu_sync_snippet1) + " " + new SimpleDateFormat("HH:mm:ss").format(new Date()));

					view.setOnClickListener(new View.OnClickListener() {
						@Override
						public void onClick(View v) {
							loadPosts();
						}
					});
				}
				
				for (int i = 0; i < mDrawerList.getChildCount(); i++){
//					mDrawerList.recomputeViewAttributes(mDrawerList.getChildAt(i));
					updateMenuItemCounter(i, 0);
				}
				
				Map<Integer, Integer> postsMap = new HashMap<Integer, Integer>();
				for (PostModel post : posts){ 
					CustomMarker customMarker = new CustomMarker(post , new LatLng(post.getLatitude(), post.getLongitude()));
					mMap.addMarker(customMarker.getMarkerOptionCustom());

					if (postsMap.get(post.getTypeKey()) == null)
						postsMap.put(post.getTypeKey(), Integer.valueOf(0));

					postsMap.put(post.getTypeKey(), postsMap.get(post.getTypeKey()) + 1);
				}

				updateMenuItemCounter(0, posts.size());
				for (Integer type : postsMap.keySet()){
					updateMenuItemCounter(type + 1, postsMap.get(type));
				}

			}

			@Override
			protected void onCancelled() {
			}

		}.execute();
	}


	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

	}

	@Override
	public void onPause() {
		super.onPause();
		m.onPause();
		if (mMap != null){
			cameraPostion = mMap.getCameraPosition();
			mMap = null;	// NAO REMOVER ESTA LINHA ! 
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (m != null)
			m.onDestroy();
	}

	@Override
	public void onStart() {
		super.onStart();

		// Connect the client.
		mLocationClient.connect();
	}

	@Override
	public void onLowMemory() {
		super.onLowMemory();
		m.onLowMemory();
	}

	private void setUpMap() {
		try {
			MapsInitializer.initialize(getActivity());
		} catch (GooglePlayServicesNotAvailableException e) {}

		mMap.setMyLocationEnabled(true);
		mMap.getUiSettings().setMyLocationButtonEnabled(false);

		mMap.getUiSettings().setZoomControlsEnabled(false);
		buildListenerEssentialMap();
	}


	@Override
	public void onConnectionFailed(ConnectionResult result) {
		if (result.hasResolution()) {

			try {
				// Start an Activity that tries to resolve the error
				result.startResolutionForResult(this.getActivity(), CONNECTION_FAILURE_RESOLUTION_REQUEST);
				/*
				 * Thrown if Google Play services canceled the original
				 * PendingIntent
				 */
			} catch (IntentSender.SendIntentException e) {
				// Log the error
				e.printStackTrace();
			}

		} else {

			/*
			 * If no resolution is available, display a dialog to the
			 * user with the error.
			 */

			Toast.makeText(this.getActivity(), "Não foi possível conectar ao Google Play Service. Por favor tente novamente mais tarde.",  Toast.LENGTH_SHORT).show();
		}
	}

	@Override
	public void onConnected(Bundle connectionHint) {
		Toast.makeText(this.getActivity(), "Conectado ao Google Play Service.",  Toast.LENGTH_SHORT).show();
		
		if (cameraPostion == null)
			goToCurrentPosition();
	}

	@Override
	public void onDisconnected() {
		Toast.makeText(this.getActivity(), "Desconectado do Google Play Service. Por favor tente novamente.",  Toast.LENGTH_SHORT).show();		
	}
}